package com.copyctrl.campus.portal.service.Impl;

import cn.hutool.json.JSONUtil;
import com.copyctrl.campus.common.constant.RedisConstant;
import com.copyctrl.campus.common.domain.User;
import com.copyctrl.campus.portal.service.FollowService;
import com.copyctrl.mapper.CampFollowMapper;
import com.copyctrl.model.CampFollow;
import com.copyctrl.model.CampFollowExample;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author:JH
 * @version:1.0
 */
@Slf4j
@Service
public class FollowServiceImpl implements FollowService {

    @Autowired
    CampFollowMapper mapper;
    @Autowired
    StringRedisTemplate stringRedisTemplate;


    @Override
    public int follow(CampFollow follow) {
        follow.setCreateTime(new Date());
        int insert = mapper.insert(follow);
        //redis中给用户的朋友列表添加关注的用户id 考虑到添加列表后要后续进行判断操作，使用多线程进行异步操作，不再使用消息队列
        executeInsert(follow);
        return insert;
    }

    @Override
    public int delete(CampFollow follow) {
        CampFollowExample example=new CampFollowExample();
        example.createCriteria().andUserIdEqualTo(follow.getUserId())
                        .andFollowEqualTo(follow.getFollow());
        int i = mapper.deleteByExample(example);
        executedelete(follow);
        return i;
    }

    @Override
    public List<User> findAllFollowers(Integer id) {
        Set members = stringRedisTemplate.opsForSet().members(RedisConstant.USER_IS_FOLLOWED + id);
        List openids = (List) stringRedisTemplate.opsForHash()
                .multiGet(RedisConstant.ID_OPENID, members)
                .stream()
                .map(openid -> RedisConstant.USER_KEY+openid.toString()).collect(Collectors.toList());
        return getUsersBykeys(openids);
    }

    @Override
    public List<User> findAllAttentions(Integer id) {
        Set members = stringRedisTemplate.opsForSet().members(RedisConstant.USER_FOLLOW + id);
        List openids = (List) stringRedisTemplate.opsForHash()
                .multiGet(RedisConstant.ID_OPENID, members)
                .stream()
                .map(openid -> RedisConstant.USER_KEY+openid.toString()).collect(Collectors.toList());
        return getUsersBykeys(openids);
    }

    @Override
    public List<User> findAllFriends(Integer id) {
        Set members = stringRedisTemplate.opsForSet().members(RedisConstant.USER_FRIEND + id);
        List openids = (List) stringRedisTemplate.opsForHash()
                .multiGet(RedisConstant.ID_OPENID, members)
                .stream()
                .map(openid -> RedisConstant.USER_KEY+openid.toString()).collect(Collectors.toList());
        return getUsersBykeys(openids);
    }

    /**
     * 异步处理关注，操作redis
     */
    @Async("defaultThreadPoolExecutor")
    public void executeInsert(CampFollow follow) {
        Integer userId = follow.getUserId();
        String redisKey=RedisConstant.USER_FOLLOW+ userId;
        //使用set存储即可,因为用户的id是唯一的，所以在这里存关注用户的id
        Integer followId = follow.getFollow();
        stringRedisTemplate.opsForSet().add(RedisConstant.USER_FOLLOW+ userId, followId.toString());
        stringRedisTemplate.opsForSet().add(RedisConstant.USER_IS_FOLLOWED+followId,userId.toString());
        Boolean member = stringRedisTemplate.opsForSet().isMember(RedisConstant.USER_FOLLOW + followId, userId.toString());
        if(member){
            //互相关注了，添加到各自的好友列表
            stringRedisTemplate.opsForSet().add(RedisConstant.USER_FRIEND+userId,followId.toString());
            stringRedisTemplate.opsForSet().add(RedisConstant.USER_FRIEND+followId,userId.toString());
        }
    }

    /**
     * 异步处理取关，操作redis
     */
    @Async("defaultThreadPoolExecutor")
    public void executedelete(CampFollow follow) {
        Integer userId = follow.getUserId();
        String redisKey=RedisConstant.USER_FOLLOW+ userId;
        Integer followId = follow.getFollow();
        stringRedisTemplate.opsForSet().remove(RedisConstant.USER_FOLLOW+ userId, followId.toString());
        stringRedisTemplate.opsForSet().remove(RedisConstant.USER_IS_FOLLOWED+followId,userId.toString());
        Boolean member = stringRedisTemplate.opsForSet().isMember(RedisConstant.USER_FOLLOW + followId, userId.toString());
        if(member){
            //互相关注了，各自从好友列表删除
            stringRedisTemplate.opsForSet().remove(RedisConstant.USER_FRIEND+userId,followId.toString());
            stringRedisTemplate.opsForSet().remove(RedisConstant.USER_FRIEND+followId,userId.toString());
        }
    }

    public List<User> getUsersBykeys(List openids){
        List<User> users=new ArrayList<>();
        List<String> jsons = stringRedisTemplate.opsForValue().multiGet(openids);
        for (String json : jsons) {
            User user = JSONUtil.toBean(json, User.class);
            users.add(user);
        }
        return users;
    }
}
